<?php

/**
 * This file is part of manage.
 * Author: tangzhou
 * Date: 2016/7/23
 * Time: 10:50
 * File: RedisSessionHandler.php
 */

namespace Icsoc\SecurityBundle\Session;

use Predis\Client;

/**
 * Class RedisSessionHandler
 *
 * @package Icsoc\SecurityBundle\Session
 */
class RedisSessionHandler implements \SessionHandlerInterface
{
    /**
     * @var \Redis
     */
    private $redis;

    /**
     * @var integer
     */
    private $lifetime;

    /**
     * @var array
     */
    private $options;

    /**
     * Constructor
     *
     * List of available options:
     *  * key_prefix: The key prefix [default: '']
     *
     * @param \Redis  $redis    The redis instance
     * @param integer $lifetime Max lifetime in seconds to keep sessions stored.
     * @param array   $options  Options for the session handler
     *
     * @throws \InvalidArgumentException When Redis instance not provided
     */
    public function __construct($redis, $lifetime, array $options = array())
    {
        if (!$redis instanceof Client) {
            throw new \InvalidArgumentException('Redis instance required');
        }
        $this->redis = $redis;
        $this->lifetime = $lifetime;
        if (!is_array($options)) {
            $options = array();
        }
        $this->options = $options;
    }

    /**
     * Re-initializes existing session, or creates a new one.
     *
     * @see http://php.net/sessionhandlerinterface.open
     *
     * @param string $savePath    Save path
     * @param string $sessionName Session name, see http://php.net/function.session-name.php
     *
     * @return bool true on success, false on failure
     */
    public function open($savePath, $sessionName)
    {
        return true;
    }

    /**
     * Reads the session data.
     *
     * @see http://php.net/sessionhandlerinterface.read
     *
     * @param string $sessionId Session ID, see http://php.net/function.session-id
     *
     * @return string Same session data as passed in write() or empty string when non-existent or on failure
     */
    public function read($sessionId)
    {
        $key = $this->getKey($sessionId);

        return (string) $this->redis->get($key);
    }

    /**
     * Writes the session data to the storage.
     *
     * Care, the session ID passed to write() can be different from the one previously
     * received in read() when the session ID changed due to session_regenerate_id().
     *
     * @see http://php.net/sessionhandlerinterface.write
     *
     * @param string $sessionId Session ID , see http://php.net/function.session-id
     * @param string $data      Serialized session data to save
     *
     * @return bool true on success, false on failure
     */
    public function write($sessionId, $data)
    {
        $key = $this->getKey($sessionId);

        return $this->redis->setex($key, $this->lifetime, $data);
    }

    /**
     * Destroys a session.
     *
     * @see http://php.net/sessionhandlerinterface.destroy
     *
     * @param string $sessionId Session ID, see http://php.net/function.session-id
     *
     * @return bool true on success, false on failure
     */
    public function destroy($sessionId)
    {
        $key = $this->getKey($sessionId);

        return 1 === $this->redis->del(array($key));
    }

    /**
     * Cleans up expired sessions (garbage collection).
     *
     * @see http://php.net/sessionhandlerinterface.gc
     *
     * @param string|int $maxlifetime Sessions that have not updated for the last maxlifetime seconds will be removed
     *
     * @return bool true on success, false on failure
     */
    public function gc($maxlifetime)
    {
        /* Note: Redis will handle the expiration of keys with SETEX command
         * See: http://redis.io/commands/setex
         */
        return true;
    }

    /**
     * Closes the current session.
     *
     * @see http://php.net/sessionhandlerinterface.close
     *
     * @return bool true on success, false on failure
     */
    public function close()
    {
        return true;
    }

    /**
     * Get the redis key
     *
     * @param string $sessionId session id
     *
     * @return string
     */
    protected function getKey($sessionId)
    {
        return $sessionId;
    }
}
